#include <stdio.h>
#include <stdlib.h>
#define ERROR 0
#define OVERFLOW -1
#define OK 1
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef int Status;
typedef int SElemType;
typedef struct
{
  SElemType *base;
  SElemType *top;
  int stackSize;
} SqStack;

/**
 * 初始化栈
 */
SqStack initStack()
{
  SqStack S;
  S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
  if (!S.base)
    exit(OVERFLOW);
  S.top = S.base;
  S.stackSize = STACK_INIT_SIZE;
  return S;
}

/**
 * @brief 将元素压入栈
 * @param S 指向栈的指针
 * @param e 要压入栈的元素
 * @return 状态码
 */
Status Push(SqStack *S, SElemType e)
{
  if (S->top - S->base >= S->stackSize)
  {
    S->base = (SElemType *)realloc(S->base, (S->stackSize + STACKINCREMENT) * sizeof(SElemType));
    if (!S->base)
      exit(OVERFLOW);
    S->top = S->base + S->stackSize;
    S->stackSize += STACKINCREMENT;
  }
  *S->top++ = e;
  // 将元素压入栈中 * 等价于以下两句代码
  /**
   * 在栈操作中，S->top 指针通常指向栈顶元素的下一个空闲位置（即当前栈顶元素的下一个地址）
   *
   * 取S->top的当前值，这是一个指针。
   * 将e的值写入S->top所指向的内存地址。
   * 将S->top增加1，使其指向下一个空闲位置。
   *
   * *S->top = e;         // 将 e 的值存入 S->top 指向的位置
   * S->top = S->top + 1; // 移动 top 指针到下一个空闲位置
   */
  return OK;
}

/**
 * @brief 将栈顶元素弹出
 * @param S 指向栈的指针
 * @param e 存放弹出元素的指针
 * @return 状态码
 */
Status Pop(SqStack *S, SElemType *e)
{
  if (S->top == S->base)
  {
    printf("Stack is empty!\n");
    return ERROR;
  }
  *e = *--S->top;
  // 从栈顶弹出元素 * 等价于以下两句代码
  /**
   * S->top = S->top - 1; // 移动 top 指针指向栈顶元素
   * *e = *S->top;        // 读取栈顶元素的值并存入 e
   */
  return OK;
}

/**
 * @brief 获取栈顶元素
 * @param S 指向栈的指针
 * @param e 存放栈顶元素的指针
 * @return 状态码
 */
Status GetTop(SqStack *S, SElemType *e)
{
  if (S->top == S->base)
  {
    printf("Stack is empty!\n");
    return ERROR;
  }
  *e = *(S->top - 1);
  return OK;
}

/**
 * 打印栈元素
 * @param S 指向栈的指针
 */
void printStack(SqStack *S)
{
  if (S->top == S->base)
  {
    printf("Stack is empty!\n");
    return;
  }
  printf("Stack elements are: ");
  for (SElemType *p = S->base; p < S->top; p++)
  {
    printf("%d ", *p);
  }
  printf("\n");
}

/**
 * 释放栈空间
 * @param S 指向栈的指针
 */
int freeStack(SqStack *S)
{
  if (S)
  {
    free(S->base);
    S->base = NULL;
    S->top = NULL;
    S->stackSize = 0;
  }
  return OK;
}

int main()
{
  int i;
  SqStack s = initStack();
  for (int i = 1; i <= 10; i++)
  {
    Push(&s, i);
  }

  printStack(&s);
  Pop(&s, &i);
  printf("Popped element: %d\n", i);
  GetTop(&s, &i);
  printf("Top element: %d\n", i);
  freeStack(&s);

  return 0;
}